/**
* project3D Engine
* @author John Sword
* Lame attempt at creating a lighted texture material
* @version 2 - AS3
*/

package engine.materials
{
	
	import engine.materials.Material;
	import engine.geom.Face;
	import flash.display.Sprite;
	import flash.display.Graphics;
	import flash.geom.Matrix;
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import engine.geom.Vector;
	import engine.math.VectorUtils;
	
	public class Texture3D extends Material
	{

		//public var wireSize:Number = 0;
		//public var wireColor:Number = 0xFFFFFF;
		//public var wireAlpha:Number = 0;
		public var lightPos:Vector = new Vector(1,1,1);
		public var red:int = 255;
		public var green:int = 255;
		public var blue:int = 255;
		
		private static const cos:Function = Math.cos;
		private static const norm:Function = VectorUtils.Normalize;
		private static const dot:Function = VectorUtils.dot;

		public function Texture3D ( tex:BitmapData, lp:Vector, r:int=255, g:int=255, b:int=255, flip:Boolean = true )
		{
			super( tex );
			if(flip)
			{
				// flip texture
				// needs a temp mc to apply the invert matrix
				var texMc:Sprite = new Sprite();
				var bmp:Bitmap = new Bitmap ( tex );
				// apply texture to temp mc
				texMc.addChild( bmp );
				// apply invert
				var textureMatrix:Matrix = new Matrix();
				textureMatrix.a = 1;
				textureMatrix.b = 0;
				textureMatrix.c = 0;
				textureMatrix.d = -1;
				textureMatrix.tx = 0;
				textureMatrix.ty = tex.height;
				// recreate texture
				this.texture = new BitmapData(texMc.width, texMc.height, true, 0x00000000);
				this.texture.draw(texMc, textureMatrix);
			} else {
				this.texture = tex;
			}
			lightPos = lp;
			red = r;
			green = g;
			blue = b;
		}
		
		public override function render ( face:Face, screen:Sprite ) : void
		{
			// get vertices x,y positions
			var v0:Object = face.v1;
			var v1:Object = face.v2;
			var v2:Object = face.v3;

			var x0:Number = v0.x,
			y0:Number = v0.y,
			z0:Number = v0.z,
			x1:Number = v1.x,
			y1:Number = v1.y,
			z1:Number = v1.z,
			x2:Number = v2.x,
			y2:Number = v2.y,
			z2:Number = v2.z;

			var MAXLIGHT:Number = 32;
			// calculate polygon normal
			// norm = CrossProduct( SubVect(p2 ,p1), SubVect( p0,p1) ); 
			var nx:Number = ( ( y0 - y1 ) * ( z0 - z2 ) ) - ( ( z0 - z1 ) * ( y0 - y2 ) );
			var ny:Number = ( ( z0 - z1 ) * ( x0 - x2 ) ) - ( ( x0 - x1 ) * ( z0 - z2 ) );
			var nz:Number = ( ( x0 - x1 ) * ( y0 - y2 ) ) - ( ( y0 - y1 ) * ( x0 - x2 ) );
			var PlaneNormal:Vector = new Vector ( nx, ny, nz );
			// fix light
			if ( lightPos.x == 0 ) lightPos.x = 1;
			if ( lightPos.y == 0 ) lightPos.y = 1;
			if ( lightPos.z == 0 ) lightPos.z = 1;

			// first get light's position
			var lightNormal:Vector = new Vector ( -lightPos.x, lightPos.y, -lightPos.z );
			// calculate normals
			PlaneNormal = norm ( PlaneNormal );
			lightNormal = norm ( lightNormal );
			// calculate angle of insidence
			var vdot:Number = dot ( PlaneNormal,lightNormal );	
			var light:Number = cos ( MAXLIGHT + vdot );
			
			if(light<0)light=0; // black is black
			
			var cr:Number = (red * light);
			var cg:Number = (green * light);
			var cb:Number = (blue * light);
			
			var fColor:Number = cr << 16 | cg << 8 | cb;
			
			// Draw triangle
			var g:Graphics = screen.graphics;
			
			x0 = v0.screen.x;
			y0 = v0.screen.y;
			x1 = v1.screen.x;
			y1 = v1.screen.y;
			x2 = v2.screen.x;
			y2 = v2.screen.y;

			g.beginBitmapFill( texture, face.getTextureMatrix(), false, false );
			//g.lineStyle( wireSize, wireColor, wireAlpha);
			
			// Draw triangle
			g.moveTo( x0, y0 );
			g.lineTo( x1, y1 );
			g.lineTo( x2, y2 );
			g.endFill();
			
			// Draw triangle
			g.beginFill( fColor, .2 );
			
			g.moveTo( x0, y0 );
			g.lineTo( x1, y1 );
			g.lineTo( x2, y2 );
		}
		
	}
	
}
